import random
from _Qfunc.same_func import get_methods  # 类内方法获取


# 判断方式
class JugMethod:
    """
    - 方法装填 内部可改参数获取模式
    - 数据准备 数值获取策略
    - 判断方法 装填方法内容，读取相应方法
        书写规范要求：判断方法统一方式way[NUM]，判断方法way__[NUM]

    三个分区由注释标明分割，顺序与上述注释一致
    """

    # funclist [方法1,方法2...]
    def __init__(self, num, funclist=None, parmlist=None, base_case=None):
        if funclist is None:  # 装填功能列表
            funclist = self.rdom_func(num)
        self.funclist = funclist

        if base_case is None:  # 装填对应不同方法的参数列表
            base_case = [800, 90, 1, 255, 400]
        self.base_case = base_case

        if parmlist is None:  # 装填对应功能列表的参数
            parmlist = self.rdom_parm()
        self.parmlist = parmlist

    # ####################################### hello world ~
    '''# # # # # # # 方  法  装  填 # # # # # # #
 |     |   |  | | || method to fill || | |  |   |     |
*-------------------------------======================================'''

    def just_doit(self, block):
        """集成简化操作"""
        self.data_on(block)
        lis = self.doit()
        return lis

    # block为3x3的矩阵
    def data_on(self, block):
        """数据装填"""
        for i in range(len(block)):  # 转为int类型
            block[i] = int(block[i])

        self.other = block[:4] + block[5:]  # 预填装各分类
        self.block = block
        self.n = block[4]
        self.allin = sum(block)

    def doit(self):
        """批量执行"""
        results = []
        for i in range(len(self.funclist)):
            result = getattr(self, self.funclist[i])(*self.parmlist[i])
            results.append(result)
        return results

    def rdom_func(self, num):
        """随机功能列表返回"""
        lis = []
        func = get_methods(self, 'way_')
        for i in range(num):
            lis.append(random.choice(func))
        if num == 0:    # 0时返回所有功能列
            return func
        return lis

    def rdom_parm(self):
        """随机产出一组参数"""
        lis = []
        for func in self.funclist:
            if func == 'way_and' or func == 'way_or':  # 分组情况选取

                tem = []  # 方法
                temp = []  # 子方法

                for k, v in self.for_and_or().items():
                    tem.append(int(k))
                    temp.append(int(v))

                # 随机选取方法后，根据参数基础表单，进行区间内随机选值
                i = int(random.choice(tem))
                datum = self.base_case[i - 1]
                dat = int(datum * 0.4)  # 区间获取，改这里的数字对应倍率
                rdom = random.randint(datum - dat, datum + dat)

                li = [i, rdom]
                l = [i for i in range(1, temp[i - 1] + 1)]
                for k in range(random.randint(1, temp[i - 1])):
                    t = random.choice(l)
                    l.remove(t)
                    li.append(t)

                lis.append(li)
            else:  # 一般情况
                choice = int(func[5])
                datum = self.base_case[choice - 1]
                dat = int(datum * 0.8)  # 区间获取，改这里的数字对应倍率
                if dat < 10:  # 对于过小值，进行随机补正
                    dat = random.randint(0, 10)
                rdom = random.randint(datum - dat, datum + dat)
                lis.append([rdom])
        return lis

    def for_and_or(self):
        """方法信息获取"""
        tem = {}
        tmp = get_methods(self, 'way__')
        for i in tmp:
            tem[int(i[i.find('way__') + 5:i.rfind('_')])] = int(i[i.rfind('_') + 1:])
        return tem  # {方法分类:最末位方法序号(默认1至序号内容都存在，否则会报错)}

    # ####################################### hello world ~
    ''' # # # # # # # 数  据  准  备 # # # # # # #
|     |   |  | | || data preparation || | |  |   |     |
*-------------------------------======================================'''

    def lut(self):
        return self.block[0] + self.block[1] + self.block[3]  # 左上 上三角

    def llt(self):
        return self.block[3] + self.block[6] + self.block[7]  # 左下 下三角

    def rut(self):
        return self.block[1] + self.block[2] + self.block[5]  # 右上 上三角

    def rlt(self):
        return self.block[5] + self.block[7] + self.block[8]  # 右下 下三角

    def ls(self):
        return self.block[0] + self.block[8]  # 左->右 斜线(不包含中心点) \

    def rs(self):
        return self.block[2] + self.block[6]  # 右->左 斜线(不包含中心点) /

    def cs(self):
        return self.block[3] + self.block[5]  # 横线(不包括中心点)  -

    def vs(self):
        return self.block[1] + self.block[7]  # 竖线(不包括中心点)  |

    def rdom(self, n=1):  # 随机取n个非中心值
        if n >= 8:
            return sum(self.other)
        elif n <= 0:
            return 0

        tmp = self.other.copy()
        lis = []
        for i in range(n):
            t = random.choice(tmp)
            lis.append(t)
            tmp.remove(t)
        return sum(lis)

    # ####################################### hello world ~
    '''# # # # # # # 判  断  方  法 # # # # # # #
|     |   |  | | || Judgment Method || | |  |   |     |
*-------------------------------======================================'''

    # 传入参数说明
    # func{str}_将会调用的方法编号 支持列表形式，一般情况下默认为单值
    # x{int}_注入的参数
    # *args{str}_子方法编号   当func取列表时，需要一一对应且存在
    def way_and(self, func, x, *args):
        k = 0
        for i in args:
            if isinstance(func, list):
                f = func[k]
                k += 1
            else:
                f = func

            funcname = f'way__{f}_{i}'
            if not getattr(self, funcname)(x):
                return False
        return True

    def way_or(self, func, x=40000, *args):
        k = 0
        for i in args:
            if isinstance(func, list):
                f = func[k]
                k += 1
            else:
                f = func

            funcname = f'way__{f}_{i}'
            if getattr(self, funcname)(x):
                return True
        return False

    '''
# 1 # 1 ## 1 1 ### 一 # 1 #### 一 ## 1 ########## 一 #####################
    # 玄学判断法，提取线稿
    '''

    def way1_mod(self, n, x):
        if abs(n - self.n) ** 2 > x:
            return True
        return False

    def way__1_1(self, x):
        n = int(self.lut() / 3)
        return self.way1_mod(n, x)

    def way__1_2(self, x):
        n = int(self.ls() / 2)
        return self.way1_mod(n, x)

    def way__1_3(self, x):
        n = int((self.block[0] + self.block[3] + self.block[5] + self.block[6]) / 4)
        return self.way1_mod(n, x)

    def way__1_4(self, x):
        n = int((self.block[1] + self.block[4]) / 2)
        return self.way1_mod(n, x)

    def way__1_5(self, x, i=2):
        """随机取{i}个其他值的均值"""
        n = int((self.rdom(i)) / i)
        return self.way1_mod(n, x)

    '''
# 2 # 2 ## 2 2 ### 二 # 2 #### 二 ## 2 ########## 二 #####################    
    # 硬性判断，灰度像素分布于0[黑]-255[白]，可以保留暗部
    '''

    def way__2_1(self, x):
        """x值以下的内容为真"""
        if self.n < x:
            return True
        return False

    def way__2_2(self, x):
        """玄学"""
        if self.n < (x ** 2) % 255:
            return True
        return False

    def way__2_3(self, x):
        """玄学"""
        n = (self.n * random.randint(0, x)) % 255
        if self.n < n:
            return True
        return False

    '''
# 3 # 3 ## 3 3 ### 三 # 3 #### 三 ## 3 ########## 三 #####################
    # 对于所有分散在周围的像素取色，生成噪点，线稿提取
    '''

    def way__3_1(self, x=0):
        """中心点与外围均值比大小,x与中心点值相加"""
        num = sum(self.other)
        num = int(num / 8)
        if self.n + x < num:
            return True
        return False

    def way__3_2(self, x=0):
        """"""
        num = int(self.allin / 8)
        if self.n + x < num:
            return True
        return False

    '''
# 4 # 4 ## 4 4 ### 四 # 4 #### 四 ## 4 ########## 四 #####################
    # 玄学检测
    '''

    def way__4_1(self, x=255):
        """[疑似光敏]"""
        n1 = random.choice(self.other)
        n2 = sum(self.other) % x
        if n1 > n2:
            return True
        return False

    def way__4_2(self, x=255):
        """"""
        n1 = self.n
        n2 = sum(self.other) % x
        if n1 > n2:
            return True
        return False

    '''
# 5 # 5 ## 5 5 ### 五 # 5 #### 五 ## 5 ########## 五 #####################
    # 线性检测
    '''

    def way5_mod(self, n, x):
        if self.allin - n * 2 < x:
            return True
        return False

    # 斜向 \
    def way__5_1(self, x):
        n = self.ls() + self.n
        return self.way5_mod(n, x)

    # 斜向 /
    def way__5_2(self, x):
        n = self.rs() + self.n
        return self.way5_mod(n, x)

    # 横向 -
    def way__5_3(self, x):
        n = self.cs() + self.n
        return self.way5_mod(n, x)

    # 竖向 |
    def way__5_4(self, x):
        n = self.vs() + self.n
        return self.way5_mod(n, x)

    # 十字准心 +
    def way__5_5(self, x):
        n = self.vs() + self.cs()
        return self.way5_mod(n, x)

    # 十字准心 +
    def way__5_6(self, x):
        n = self.ls() + self.rs()
        return self.way5_mod(n, x)